using UnityEngine;
using DG.Tweening;
using System;

/// <summary>
/// 螺旋前进移动策略
/// </summary>
public class SpiralMovement : IMovementStrategy
{
    /// <summary>
    /// 螺旋半径
    /// </summary>
    private readonly float m_Radius;
    /// <summary>
    /// 旋转圈数
    /// </summary>
    private readonly float m_Rotations;
    /// <summary>
    /// 是否顺时针旋转
    /// </summary>
    private readonly bool m_Clockwise;   

    public SpiralMovement(float radius = 1f, float rotations = 3f, bool clockwise = true)
    {
        m_Radius = Mathf.Max(0.1f, radius);
        m_Rotations = Mathf.Max(0.1f, rotations);
        m_Clockwise = clockwise;
    }

    public void Move(GameObject bullet, Vector3 start, Vector3 end, float duration, Action callback)
    {
        // 计算前进方向
        Vector3 direction = (end - start).normalized;
        float distance = Vector3.Distance(start, end);

        // 建立参考坐标系
        Vector3 right, up;
        CreateCoordinateSystem(direction, out right, out up);

        // 初始位置
        bullet.transform.position = start;

        // 使用DOTween来实现螺旋运动
        Sequence spiralSequence = DOTween.Sequence();

        // 位置更新
        spiralSequence.Append(DOTween.To(
            t => {
                // 直线前进
                float linearProgress = t;
                Vector3 linearPos = Vector3.Lerp(start, end, linearProgress);

                // 螺旋运动
                float angle = 2 * Mathf.PI * m_Rotations * t;
                if (!m_Clockwise) angle = -angle; // 逆时针旋转

                Vector3 offset = right * Mathf.Cos(angle) * m_Radius
                               + up * Mathf.Sin(angle) * m_Radius;

                // 应用位置
                bullet.transform.position = linearPos + offset;
            },
            0, 1, duration
        ));

        // 完成回调
        spiralSequence.OnComplete(() => callback?.Invoke());
    }

    /// <summary>
    /// 创建垂直于前进方向的坐标系
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="right"></param>
    /// <param name="up"></param>
    private void CreateCoordinateSystem(Vector3 direction, out Vector3 right, out Vector3 up)
    {
        // 使用世界坐标系的上方向作为初始参考
        Vector3 referenceUp = Vector3.up;

        // 如果前进方向与上方向平行，则用右方向作为参考
        if (Mathf.Abs(Vector3.Dot(direction, referenceUp)) > 0.99f)
        {
            referenceUp = Vector3.right;
        }

        // 计算右方向（垂直于前进方向）
        right = Vector3.Cross(direction, referenceUp).normalized;

        // 计算上方向，确保与前进方向和右方向垂直
        up = Vector3.Cross(right, direction).normalized;
    }
}